/*!
 * \file WtSelEngine.h
 * \project	WonderTrader
 *
 * \author Wesley
 * \date 2020/03/30
 * 
 * \brief SEL选股引擎头文件
 * 
 * 本文件定义了SEL(Selection)选股引擎类，用于处理选股策略的执行、
 * 任务调度、定时执行等功能。SEL引擎主要用于股票选股、组合管理等场景。
 */
#pragma once
#include "WtEngine.h"
#include "WtExecMgr.h"

#include "../Includes/FasterDefs.h"
#include "../Includes/ISelStraCtx.h"

#include <memory>

NS_WTP_BEGIN

/**
 * @enum TaskPeriodType
 * @brief 任务周期类型枚举
 * 
 * 定义了选股任务的执行周期类型
 */
typedef enum tagTaskPeriodType
{
	TPT_None,		/**< 不重复 */
	TPT_Minute = 4,	/**< 每分钟重复 */
	TPT_Daily = 8,	/**< 每天重复 */
	TPT_Weekly,		/**< 每周，需要指定星期几，还要顺延 */
	TPT_Monthly,	/**< 每月，需要指定几号顺延 */
	TPT_Yearly		/**< 每年，需要指定几号顺延 */
}TaskPeriodType;

/**
 * @struct _TaskInfo
 * @brief 任务信息结构体
 * 
 * 定义了选股任务的详细信息，包括执行时间、周期、模板等
 */
typedef struct _TaskInfo
{
	uint32_t	_id;			/**< 任务ID */
	char		_name[16];		/**< 任务名称 */
	char		_trdtpl[16];	/**< 交易日模板 */
	char		_session[16];	/**< 交易时段模板 */
	uint32_t	_day;			/**< 日期，如果是周期变化，每天为0，每周为0~6，对应周日到周六，每月为1~31，每年为0101~1231 */
	uint32_t	_time;			/**< 时间，精确到分钟 */
	bool		_strict_time;	/**< 是否严格按时间，严格时间的话只有时间完全吻合才会执行，不严格时间，则在当天大于此时间都会执行 */

	uint64_t	_last_exe_time;	/**< 上次执行时间，主要为了防止重复执行 */

	TaskPeriodType	_period;	/**< 任务周期 */
} TaskInfo;

typedef std::shared_ptr<TaskInfo> TaskInfoPtr;

typedef std::shared_ptr<ISelStraCtx> SelContextPtr;
class WtSelRtTicker;

/**
 * @class WtSelEngine
 * @brief SEL选股引擎类
 * 
 * SEL引擎是WonderTrader系统中专门用于选股策略的核心组件，
 * 继承自WtEngine基类和IExecuterStub接口，提供选股策略的运行环境。
 * 
 * 主要功能包括：
 * - 选股策略管理和执行
 * - 任务调度和定时执行
 * - 股票组合管理
 * - 执行器管理
 * - 持仓变化处理
 * 
 * @note SEL引擎主要用于股票选股、量化投资组合管理等场景
 * @see WtEngine, IExecuterStub
 */
class WtSelEngine : public WtEngine, public IExecuterStub
{
public:
	/**
	 * @brief 构造函数
	 */
	WtSelEngine();
	
	/**
	 * @brief 析构函数
	 */
	~WtSelEngine();

public:
	//////////////////////////////////////////////////////////////////////////
	// WtEngine接口
	
	/**
	 * @brief 初始化SEL引擎
	 * 
	 * @param cfg 配置对象
	 * @param bdMgr 基础数据管理器
	 * @param dataMgr 数据管理器
	 * @param hotMgr 热点管理器
	 * @param notifier 事件通知器
	 */
	virtual void init(WTSVariant* cfg, IBaseDataMgr* bdMgr, WtDtMgr* dataMgr, IHotMgr* hotMgr, EventNotifier* notifier) override;

	/**
	 * @brief 运行SEL引擎
	 * 
	 * @param bAsync 是否异步运行，默认为false
	 */
	virtual void run(bool bAsync = false) override;

	/**
	 * @brief 处理tick数据
	 * 
	 * @param stdCode 标准合约代码
	 * @param curTick 当前tick数据
	 */
	virtual void on_tick(const char* stdCode, WTSTickData* curTick) override;

	/**
	 * @brief 处理K线数据
	 * 
	 * @param stdCode 标准合约代码
	 * @param period 周期
	 * @param times 倍数
	 * @param newBar 新的K线数据
	 */
	virtual void on_bar(const char* stdCode, const char* period, uint32_t times, WTSBarStruct* newBar) override;

	/**
	 * @brief 处理推送的行情数据
	 * 
	 * @param newTick 新的tick数据
	 * @param hotFlag 热点标志
	 */
	virtual void handle_push_quote(WTSTickData* newTick, uint32_t hotFlag) override;

	/**
	 * @brief 初始化事件处理
	 */
	virtual void on_init() override;

	/**
	 * @brief 交易时段开始事件处理
	 */
	virtual void on_session_begin() override;

	/**
	 * @brief 交易时段结束事件处理
	 */
	virtual void on_session_end() override;

	///////////////////////////////////////////////////////////////////////////
	// IExecuterStub 接口
	
	/**
	 * @brief 获取实时时间
	 * 
	 * @return 实时时间戳
	 */
	virtual uint64_t get_real_time() override;
	
	/**
	 * @brief 获取品种信息
	 * 
	 * @param stdCode 标准合约代码
	 * @return 品种信息指针
	 */
	virtual WTSCommodityInfo* get_comm_info(const char* stdCode) override;
	
	/**
	 * @brief 获取交易时段信息
	 * 
	 * @param stdCode 标准合约代码
	 * @return 交易时段信息指针
	 */
	virtual WTSSessionInfo* get_sess_info(const char* stdCode) override;
	
	/**
	 * @brief 获取热点管理器
	 * 
	 * @return 热点管理器指针
	 */
	virtual IHotMgr* get_hot_mon() { return _hot_mgr; }
	
	/**
	 * @brief 获取交易日
	 * 
	 * @return 当前交易日
	 */
	virtual uint32_t get_trading_day() { return _cur_tdate; }

public:
	/**
	 * @brief 添加选股策略上下文
	 * 
	 * @param ctx 策略上下文指针
	 * @param date 执行日期
	 * @param time 执行时间
	 * @param period 执行周期
	 * @param bStrict 是否严格按时间执行，默认为true
	 * @param trdtpl 交易日模板，默认为\"CHINA\"
	 * @param sessionID 交易时段ID，默认为\"TRADING\"
	 */
	void			addContext(SelContextPtr ctx, uint32_t date, uint32_t time, TaskPeriodType period, bool bStrict = true, const char* trdtpl = "CHINA", const char* sessionID="TRADING");

	/**
	 * @brief 获取策略上下文
	 * 
	 * @param id 策略ID
	 * @return 策略上下文指针，如果不存在则返回空指针
	 */
	SelContextPtr	getContext(uint32_t id);

	/**
	 * @brief 添加执行器
	 * 
	 * @param executer 执行器指针
	 */
	inline void addExecuter(ExecCmdPtr& executer)
	{
		_exec_mgr.add_executer(executer);
		executer->setStub(this);
	}

	/**
	 * @brief 分钟结束事件处理
	 * 
	 * @param uDate 日期
	 * @param uTime 时间
	 */
	void	on_minute_end(uint32_t uDate, uint32_t uTime);

	/**
	 * @brief 处理持仓变化
	 * 
	 * @param stdCode 标准合约代码
	 * @param diffQty 持仓变化量
	 */
	void	handle_pos_change(const char* stdCode, double diffQty);

private:
	/**< 任务信息映射表 */
	faster_hashmap<uint32_t, TaskInfoPtr>	_tasks;

	/**< 策略上下文映射表 */
	typedef faster_hashmap<uint32_t, SelContextPtr> ContextMap;
	ContextMap		_ctx_map;

	/**< 执行管理器 */
	WtExecuterMgr	_exec_mgr;

	/**< 是否已终止 */
	bool	_terminated;

	/**< 实时ticker */
	WtSelRtTicker*	_tm_ticker;
	
	/**< 配置对象 */
	WTSVariant*		_cfg;
};

NS_WTP_END
